﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Publicuse.Util
{
    /// <summary>
    /// 反射对象池
    /// </summary>
    public class ReflectionObjectPoolUtil
    {
        // 参数对象属性列表缓存数目
        static int nPropertiesCount = 100;

        // 存池满时清理最长时间没有对象的数量
        static int nOverClearCount = 20;

        static Hashtable htCacheAttribute = new Hashtable(); // 参数对象属性的列表

        /// <summary>
        /// 获取或设置缓存池对象数量（默认100）
        /// </summary>
        public static int CacheObjectPoolCount
        {
            get { return nPropertiesCount; }
            set { nPropertiesCount = value; }
        }


        /// <summary>
        /// 获取或设置缓存池满时清理最长时间没有对象的数量（默认20）
        /// </summary>
        public static int OverClearCount
        {
            get { return nOverClearCount; }
            set { nOverClearCount = value; }
        }


        /// <summary>
        /// 获取对象的属性列表
        /// </summary>
        /// <param name="sClassFullName">该对象的类型全名</param>
        /// <param name="objPara">要进行获取的对象</param>
        /// <returns></returns>
        public static Hashtable GetProperties(object objPara)
        {
            Type t = objPara.GetType();
            string sClassFullName = t.FullName;
            //假如缓存有直接从缓存获取
            if (htCacheAttribute.ContainsKey(sClassFullName))
            {
                CacheUnit cspTemp = htCacheAttribute[sClassFullName] as CacheUnit;
                cspTemp.RefreshLastUsedTime();

                return (Hashtable)cspTemp.Value;
            }
            PropertyInfo[] arrPropertyInfo = t.GetProperties();
            // 将属性的数组集合转换为Hashtable
            Hashtable ht = new Hashtable();
            foreach (PropertyInfo pp in arrPropertyInfo)
                ht.Add(pp.Name.ToLower(), pp);

            SetCacheProperties(sClassFullName, ht); // 设置缓存
            return ht;

        }

        /// <summary>
        /// 设置缓存
        /// </summary>
        static void SetCacheProperties(string sFullClassName, object arrProperties)
        {
            if (htCacheAttribute.Count >= nPropertiesCount) // 假如缓存集合表里边的数目大于等于规定的值时将最长时间没有的20条数据清掉
            {
                ArrayList al = new ArrayList(htCacheAttribute.Values);
                al.Sort(); // 升序排序

                for (int i = 0; i < nOverClearCount; i++) //移除最早的20条数据
                {
                    CacheUnit csp = (CacheUnit)al[i];
                    htCacheAttribute.Remove(csp.Key);
                }

            }
            if (!htCacheAttribute.Contains(sFullClassName))
                htCacheAttribute.Add(sFullClassName, new CacheUnit(sFullClassName, arrProperties));
        }
    }

    /// <summary>
    /// 缓存单元类
    /// </summary>
    public class CacheUnit : IComparable
    {
        public CacheUnit(string sKey, object oValue)
        {
            Key = sKey;
            Value = oValue;
            UpdateTime = DateTime.Now;
        }
        /// <summary>
        /// 缓存键值
        /// </summary>
        public string Key { get; set; }

        /// <summary>
        /// 缓存对象
        /// </summary>
        public object Value { get; set; }

        /// <summary>
        /// 最后使用时间
        /// </summary>
        public DateTime UpdateTime { get; set; }

        /// <summary>
        /// 更新最后使用时间
        /// </summary>
        public void RefreshLastUsedTime()
        {
            UpdateTime = DateTime.Now;
        }
        public int CompareTo(object csp)
        {
            CacheUnit curcsp = csp as CacheUnit;
            if (curcsp != null)
            {
                if (UpdateTime < curcsp.UpdateTime)
                    return -1;

                if (UpdateTime > curcsp.UpdateTime)
                    return 1;

                return 0;
            }
            else
            {
                throw new Exception("最后更新时间异常");
            }
        }
    }
}
